package cn.xd.security.config;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.xd.security.token.AdminUserCaptchaToken;
import jakarta.annotation.Resource;
import org.springframework.context.event.EventListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Component
public class AuthenticationEvents {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    private static final String freezeFormat = "AUTH:PASSWORD_FAIL_FREEZE:%s:%s";
    private static final String countFormat = "AUTH:PASSWORD_FAIL_COUNT:%s:%s";

    @EventListener
    public void onFailure(AuthenticationFailureBadCredentialsEvent failures) {
        Object source = failures.getSource();
        if (source instanceof AdminUserCaptchaToken adminUserCaptchaToken) {
            String account = StrUtil.subBefore(adminUserCaptchaToken.getName(), "@", Boolean.TRUE);
            String countKey = String.format(countFormat, adminUserCaptchaToken.getType().getAppTypeEnum().getCode(), account);
            String freezeKey = String.format(freezeFormat, adminUserCaptchaToken.getType().getAppTypeEnum().getCode(), account);
            Integer count = (Integer) redisTemplate.opsForValue().get(countKey);
            if (ObjectUtil.isEmpty(count)) {
                count = 0;
            }
            count++;
            if (count >= 5) {
                redisTemplate.opsForValue().set(freezeKey, new Date(), 5, TimeUnit.MINUTES);
            }
            redisTemplate.opsForValue().set(countKey, count, 1, TimeUnit.DAYS);
        }
    }
}
